home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mgr / sparcmgr / demo1.zoo / demo / mac / mp2mgr.hqx / MPtoMGR.pit / mptomgr.c next >
Encoding:
C/C++ Source or Header  |  1987-05-14  |  20.8 KB  |  844 lines

  1. #include <Quickdraw.h>
  2. #include <WindowMgr.h>
  3. #include <EventMgr.h>
  4. #include <ControlMgr.h>
  5. #include <MenuMgr.h>
  6. #include <DialogMgr.h>
  7. #include <FileMgr.h>
  8. #include <OSUtil.h>
  9. #include <StdFilePkg.h>
  10. #include <ToolboxUtil.h>
  11.  
  12. #define appleID            128    /* menu IDs */
  13. #define fileID            129
  14. #define editID            130
  15.  
  16. #define ErrorAlert        256    /* alert ID */
  17.  
  18. #define Formats            257    /* dialog ID */
  19.  
  20. #define chID    256        /* cross hairs cursor ID */
  21. #define mhID    257        /* move hand cursor ID */
  22.  
  23. #define apID    256        /* about page ID */
  24.  
  25. #define OPEN_ITEM    1    /* item id's in menus */
  26. #define CLOSE_ITEM    2
  27. #define SAVE_ITEM    3
  28. #define BURY_ITEM    4
  29. #define QUIT_ITEM    5
  30.  
  31. #define UNDO_ITEM    1    /* more item id's.  2 is a gray bar */
  32. #define CUT_ITEM    3
  33. #define COPY_ITEM    4
  34. #define PASTE_ITEM    5
  35. #define CLEAR_ITEM    6
  36.  
  37. #define ABOUT_ITEM 1
  38.  
  39. #define PAINT_SIZE 51840    /* macpaint size in bytes */
  40. #define PAINT_HIGH 720        /* scanlines high */
  41. #define PAINT_WIDE 576        /* bits wide */
  42.  
  43. #define MGR_FMT        3
  44. #define SUNRAST_FMT    4
  45. #define TEXT_FMT    5
  46.  
  47. CursHandle    cross_hairs, move_hand;
  48.  
  49. WindowRecord    wRecord;    /* global window record */
  50. WindowPtr    myWindow;        /* ptr to window */
  51. MenuHandle        myMenus[3];    /* list of menus */
  52. PicHandle    aboutpic;        /* PICT used for the About... window */
  53.  
  54. int quitflag;
  55. int mpopen;        /* flag for macpaint file open */
  56. int selected;    /* flag if a section has been selected */
  57. int format;        /* format of saved bitmap */
  58.  
  59. int vRef;        /* volume reference number for current file */
  60. Str255 fname;    /* general filename variable */
  61. SFReply reply;    /* reply structure from SF routines (package manager) */
  62.  
  63. int px, py, ww, wh; /* picture x, picture y, window width, window height */
  64. Rect srect; /* selection rect */
  65.  
  66. BitMap MPmap;
  67.  
  68. main()
  69. {
  70.     InitGraf(&thePort);            /* all the macintosh inits */
  71.     InitFonts();
  72.     FlushEvents(everyEvent, 0);
  73.     InitWindows();
  74.     InitMenus();
  75.     TEInit();
  76.     InitDialogs(0L);
  77.     InitCursor();
  78.     MaxApplZone();                /* gets as much memory as possible */
  79.     
  80.     GetWindow();                /* init window(s) */
  81.     GetMenus();                    /* init menus */
  82.     
  83.     quitflag = 1;                /* application specific inits */
  84.     mpopen = 0;
  85.     selected = 0;
  86.     format = MGR_FMT;
  87.     MPmap.baseAddr = 0L;
  88.     cross_hairs = GetCursor(chID);
  89.     HLock(cross_hairs);
  90.     move_hand = GetCursor(mhID);
  91.     HLock(move_hand);
  92.     aboutpic = GetPicture(apID);
  93.     SetCursor(&arrow);
  94.     
  95.     while(events());
  96. }
  97.  
  98. events()
  99. {
  100.     EventRecord myEvent;
  101.     WindowPtr        whichWindow;
  102.     Rect            r;
  103.     
  104.     SystemTask();    /* does desk accessory processing */
  105.     
  106.     MagicCursor();    /* cursor updates */
  107.     MagicMenu();    /* menu enable/disable functions */
  108.     
  109.     if (GetNextEvent(everyEvent, &myEvent)) {
  110.     /* the standard event loop */
  111.         switch (myEvent.what) {
  112.         case mouseDown:
  113.             switch (FindWindow(myEvent.where, &whichWindow)) {
  114.             /* rememer, events are in GLOBAL coordinates! */
  115.             case inDesk: 
  116.                 SysBeep(5); /* in gray area */
  117.                 break;
  118.             case inGoAway:
  119.                 break;
  120.             case inMenuBar:
  121.                 /* do menu events */
  122.                 return(DoCommand(MenuSelect(myEvent.where)));
  123.             case inSysWindow:
  124.                 /* this belongs to a desk accessory */
  125.                 SystemClick(&myEvent, whichWindow);
  126.                 break;
  127.             case inDrag:    /*in window parts */
  128.             case inGrow:
  129.                 if (whichWindow != FrontWindow())
  130.                     SelectWindow(whichWindow);
  131.                 break;
  132.             case inContent:
  133.                 if (whichWindow != FrontWindow())
  134.                     SelectWindow(whichWindow);
  135.                 else {
  136.                     if (mpopen && myEvent.modifiers & optionKey) {
  137.                         TrackHand(myEvent.where);
  138.                     }
  139.                     else if (mpopen) {
  140.                         Select(myEvent.where);
  141.                     }
  142.                 }
  143.                 break;
  144.             default: ;
  145.             } /* end switch FindWindow */
  146.             break;
  147.         case keyDown:
  148.         case autoKey: 
  149.             {
  150.             register char    theChar;
  151.             
  152.             theChar = myEvent.message & charCodeMask;
  153.             if ((myEvent.modifiers & cmdKey) != 0) 
  154.                 return( DoCommand(MenuKey(theChar)));
  155.                 /* menu equivalents */
  156.             else ; /* don't take typing */
  157.             }
  158.             break;
  159.         case activateEvt:
  160.             break;
  161.         case updateEvt:
  162.             BeginUpdate(myWindow);
  163.             if(mpopen) DispMP();
  164.             EndUpdate(myWindow);
  165.             break;
  166.         default: ;
  167.         } /* end of case myEvent.what */
  168.     } /* if */
  169.     return(quitflag);
  170. }
  171.  
  172. GetWindow()
  173. {    /* pull in a window from a resource file and show it in front */
  174.     myWindow = GetNewWindow(256, &wRecord, -1L);
  175.     ShowWindow(myWindow);
  176.     SetPort(myWindow);
  177.     ww = myWindow->portRect.right - myWindow->portRect.left;
  178.     wh = myWindow->portRect.bottom - myWindow->portRect.top;
  179. }
  180.  
  181. GetMenus()
  182. {
  183.     int i;
  184.     
  185.     /* make the apple menu */
  186.     myMenus[0] = NewMenu(appleID, "\P\024");
  187.     AppendMenu(myMenus[0], "\PAbout MPtoMGR...;(-");
  188.     /* about item definition, followed by a gray bar defined by '(-' */
  189.     AddResMenu(myMenus[0], 'DRVR'); /* add in DA's */
  190.     myMenus[1] = GetMenu(fileID);    /* get the other menus */
  191.     myMenus[2] = GetMenu(editID);
  192.     for (i=0; i< 3; i++ ) InsertMenu(myMenus[i], 0); /* build bar */
  193.     DrawMenuBar();    /* display the bar */
  194. }
  195.  
  196. int DoCommand(mResult)
  197. long mResult;
  198. {
  199.     int        theItem, temp;
  200.     Str255    name;
  201.     WindowPeek wPtr;
  202.     /* classic menu command routine */
  203.     
  204.     theItem = LoWord(mResult);
  205.     switch (HiWord(mResult)) {
  206.     case appleID:
  207.         if (theItem == 1) {
  208.             DoAboutWindow();    /* about the application */
  209.         }
  210.         else {
  211.             GetItem(myMenus[0], theItem, &name);    /* DA open */
  212.             OpenDeskAcc(&name);
  213.             SetPort(myWindow);
  214.         }
  215.         break;
  216.     case fileID:    /* file menu */
  217.         switch(theItem) {
  218.         case OPEN_ITEM:
  219.             GetMP();
  220.             break;
  221.         case CLOSE_ITEM:
  222.             CloseMP();
  223.             break;
  224.         case SAVE_ITEM:
  225.             format = Pick_Format();
  226.             SaveBM();
  227.             selected = 0;
  228.             DispMP();
  229.             break;
  230.         case BURY_ITEM:
  231.             SendBehind(myWindow, 0L); /* bury our window */
  232.             break;
  233.         case QUIT_ITEM:
  234.             quitflag = 0;
  235.             break;
  236.         default:
  237.             break;
  238.         }
  239.         break;
  240.     case editID: 
  241.         break;
  242.     }
  243.     HiliteMenu(0);
  244.     return(1);
  245. }
  246.  
  247. MagicCursor()
  248. {
  249. #define OP_LO 1                /* for finding the option key */
  250. #define OP_HI (1L << 2)        /* ditto */
  251.  
  252.     KeyMap mykeymap;
  253.     Point curspos;
  254.     static int outlast = -1;
  255.     
  256.     /* magically sets cursor types. does as little work as possible */
  257.     if (myWindow != FrontWindow() && outlast != 0) {
  258.         /* system window.  give them an arrow */
  259.         outlast = 0;
  260.         SetCursor(&arrow);
  261.     }
  262.     else if(myWindow == FrontWindow()) {
  263.         outlast = 1;
  264.         GetMouse(&curspos);
  265.         if (PtInRect(curspos, &(wRecord.port.portRect))) {
  266.             /* in our window */
  267.             GetKeys(&mykeymap);
  268.             if (mykeymap.Key[OP_LO] & (OP_HI)) {
  269.                 /* option key set, make the cursor a hand */
  270.                 SetCursor(*move_hand);
  271.             }
  272.             else SetCursor(*cross_hairs); /* cross hairs w/o option key */
  273.         }
  274.         else SetCursor(&arrow); /* outside of window, give an arrow */
  275.     }
  276. }
  277.  
  278. MagicMenu()
  279. {
  280.     static int lasttype = 1;
  281.     /* alters the enabled/disable states of menu items as needed */
  282.     /* use a static flag to limit processing when a DA is active */
  283.     if (myWindow != FrontWindow() && lasttype != 0) {
  284.         lasttype = 0;
  285.         /* our window isn't in front, disable our functions */
  286.         DisableItem(myMenus[1], OPEN_ITEM);
  287.         DisableItem(myMenus[1], CLOSE_ITEM);
  288.         DisableItem(myMenus[1], SAVE_ITEM);
  289.         DisableItem(myMenus[1], BURY_ITEM);
  290.         DisableItem(myMenus[1], QUIT_ITEM);
  291.         /* enable editing for DA's*/
  292.         EnableItem(myMenus[2], UNDO_ITEM);
  293.         EnableItem(myMenus[2], CUT_ITEM);
  294.         EnableItem(myMenus[2], COPY_ITEM);
  295.         EnableItem(myMenus[2], PASTE_ITEM);
  296.         EnableItem(myMenus[2], CLEAR_ITEM);
  297.     }
  298.     else if (myWindow == FrontWindow()) {
  299.         lasttype = 1;
  300.         /* disable editing, we don't need it */
  301.         DisableItem(myMenus[2], UNDO_ITEM);
  302.         DisableItem(myMenus[2], CUT_ITEM);
  303.         DisableItem(myMenus[2], COPY_ITEM);
  304.         DisableItem(myMenus[2], PASTE_ITEM);
  305.         DisableItem(myMenus[2], CLEAR_ITEM);
  306.         EnableItem(myMenus[1], BURY_ITEM);
  307.         EnableItem(myMenus[1], QUIT_ITEM);
  308.         if(mpopen) {
  309.             /* enable close and disable open, if something open */
  310.             EnableItem(myMenus[1], CLOSE_ITEM);
  311.             DisableItem(myMenus[1], OPEN_ITEM);
  312.         }
  313.         else {
  314.             /* enable open and disable close, if something closed */
  315.             DisableItem(myMenus[1], CLOSE_ITEM);
  316.             EnableItem(myMenus[1], OPEN_ITEM);
  317.         }
  318.         if(selected) {
  319.             /* only allow a save if something selected */
  320.             EnableItem(myMenus[1], SAVE_ITEM);
  321.         }
  322.         else {
  323.             /* otherwise disable it */
  324.             DisableItem(myMenus[1], SAVE_ITEM);
  325.         }
  326.     }
  327. }
  328.  
  329. DoAboutWindow()
  330. {
  331.     static int first = 1;
  332.     static WindowRecord abRecord;
  333.     static WindowPtr abWindow;
  334.     static Rect prect;
  335.     GrafPort *saveport;
  336.     
  337.     if (first) {
  338.         /* only do this once */
  339.         first = 0;
  340.         abWindow = GetNewWindow(257, &abRecord, -1L);
  341.         /* retrieve window from resource file */
  342.         SetOrigin(0, 0);    /* set up coords, and display rect */
  343.         SetRect(&prect, 0, 0, ((*aboutpic)->picFrame).right -
  344.             ((*aboutpic)->picFrame).left, ((*aboutpic)->picFrame).bottom -
  345.             ((*aboutpic)->picFrame).top);
  346.     }
  347.     if (abWindow) { /* the window is valid */
  348.         GetPort(&saveport);    /* save old grafport, to be nice */
  349.         SetPort(abWindow);    /* make ours current */
  350.         ShowWindow(abWindow);    /* display it */
  351.         BringToFront(abWindow);
  352.         DrawPicture(aboutpic, &prect);    /* put a picture in it */
  353.         while(!Button());    /* wait for a button press */
  354.         HideWindow(abWindow);    /* hide window and restore old port */
  355.         SetPort(saveport);
  356.     }
  357. }
  358.  
  359. GetMP()
  360. {
  361.     /* a routine to read in a macpaint document */
  362.     Ptr srcPtr, s, d;        /* pointer for packed data */
  363.     int fd, e;
  364.     register int scanline;
  365.     long fsize;
  366.     unsigned char gbuf[255];
  367.     
  368.     if (MPmap.baseAddr != 0L) DisposPtr(MPmap.baseAddr);
  369.     MPmap.baseAddr = NewPtr((long)PAINT_SIZE);
  370.     srcPtr = NewPtr((long)PAINT_SIZE);
  371.     if (srcPtr == 0L || MPmap.baseAddr == 0L){
  372.         /* can't allocate mem */
  373.         MyError("\PCan't allocate memory!", "\P");
  374.     }
  375.     else {
  376.         if (GetFileName(&fname, &vRef)) {
  377.             if((e = FSOpen(&fname, vRef, &fd)) == 0) {
  378.                 fsize = 512L;    /* skip 512 byte header */
  379.                 FSRead(fd, &fsize, srcPtr);
  380.                 GetEOF(fd, &fsize);    /* how big is the file? */
  381.                 fsize -= 512L;    /* subtract header from size */
  382.                 FSRead(fd, &fsize, srcPtr); /* read the bulk */
  383.                 FSClose(fd);    /* close the file */
  384.                 s = srcPtr;        /* use temporary pointers */
  385.                 d = MPmap.baseAddr;
  386.                 for(scanline = 0; scanline < 720; scanline++)
  387.                     UnpackBits(&s, &d, 72); /* unpack data */
  388.                 DisposPtr(srcPtr);        /* free source data */
  389.                 SetRect(&(MPmap.bounds), 0, 0, PAINT_WIDE, PAINT_HIGH);
  390.                 /* macpaint dimensions */
  391.                 MPmap.rowBytes = PAINT_WIDE / 8;
  392.                 mpopen = 1;    /* flag open macpaint */
  393.                 SetWTitle(myWindow, &fname); /* title in window */
  394.                 px = py = 0;    /* align upper corner with window */
  395.                 DispMP();    /* show the sucker */
  396.             }
  397.             else {
  398.                 sprintf(gbuf, "Error %d opening", e);
  399.                 CtoPstr(gbuf);
  400.                 MyError(gbuf, &fname);
  401.             }
  402.         }
  403.     }
  404. }
  405.  
  406. SaveBM()
  407. {
  408.     Str255 fn;
  409.     int fd, e;
  410.     long mapsize;
  411.     BitMap savemap;
  412.     char gbuf[255];
  413.  
  414.     SetRect(&(savemap.bounds), 0, 0, srect.right - srect.left,
  415.         srect.bottom - srect.top);
  416.     savemap.rowBytes = (savemap.bounds.right + 7) >> 3;
  417.     savemap.rowBytes += savemap.rowBytes & 0x1;
  418.     mapsize = savemap.rowBytes * savemap.bounds.bottom;
  419.     if ((savemap.baseAddr = NewPtr(mapsize)) == 0L) {
  420.         MyError("\PCan't allocate memory!", "\P");
  421.     }
  422.     else {
  423.         CopyBits(&(MPmap), &savemap, &srect, &(savemap.bounds),
  424.             srcCopy, 0L);
  425.         if (SetFileName(&fn, &vRef)) {
  426.         e = Create(&fn, vRef, 'EDIT', 'TEXT');
  427.             if (e == noErr || e == dupFNErr) {
  428.                 if ((e = FSOpen(&fn, vRef, &fd)) == 0) {
  429.                     switch(format) {
  430.                     case MGR_FMT:
  431.                         save_mgr(fd, &savemap);
  432.                         break;
  433.                     case SUNRAST_FMT:
  434.                         save_sunrast(fd, &savemap);
  435.                         break;
  436.                     case TEXT_FMT:
  437.                         save_text(fd, &savemap, &fn);
  438.                         break;
  439.                     default:
  440.                         break;
  441.                     }
  442.                     GetFPos(fd, &mapsize);
  443.                     SetEOF(fd, mapsize);
  444.                     FSClose(fd);
  445.                 }
  446.                 else {
  447.                     sprintf(gbuf, "Error %d opening", e);
  448.                     CtoPstr(gbuf);
  449.                     MyError(gbuf, &fname);
  450.                 }
  451.             }
  452.             else {
  453.                 sprintf(gbuf, "Error %d creating", e);
  454.                 CtoPstr(gbuf);
  455.                 MyError(gbuf, &fname);
  456.             }
  457.         }
  458.         DisposPtr(savemap.baseAddr);
  459.     }    
  460. }
  461.  
  462. save_mgr(fd, map)
  463. int fd;
  464. BitMap *map;
  465. {
  466.     struct mgr_head {
  467.         unsigned char magic[2];
  468.         unsigned char h_wide;
  469.         unsigned char l_wide;
  470.         unsigned char h_high;
  471.         unsigned char l_high;
  472.     } h;
  473.     long size;
  474.     
  475.     h.magic[0] = 'z';
  476.     h.magic[1] = 'z';
  477.     h.h_wide = (((map->bounds.right)>>6)&0x3f) + ' ';
  478.     h.l_wide = ((map->bounds.right)&0x3f) + ' ';
  479.     h.h_high = (((map->bounds.bottom)>>6)&0x3f) + ' ';
  480.     h.l_high = ((map->bounds.bottom)&0x3f) + ' ';
  481.     size = (long)sizeof(struct mgr_head);
  482.     FSWrite(fd, &size, &h);
  483.     size = map->rowBytes * (long)map->bounds.bottom;
  484.     FSWrite(fd, &size, map->baseAddr);
  485. }
  486.  
  487. save_sunrast(fd, map)
  488. int fd;
  489. BitMap *map;
  490. {
  491.     struct rast_head {
  492.         long ras_magic;
  493.         long ras_width;
  494.         long ras_height;
  495.         long ras_depth;
  496.         long ras_length;
  497.         long ras_type;
  498.         long ras_maptype;
  499.         long ras_maplength;
  500.     } h;
  501.     long size;
  502.     
  503.     h.ras_magic = 0x59a66a95;
  504.     h.ras_width = map->bounds.right;
  505.     h.ras_height = map->bounds.bottom;
  506.     h.ras_depth = 1L;
  507.     h.ras_length = map->rowBytes * (long)map->bounds.bottom;
  508.     h.ras_type = 1L;
  509.     h.ras_maptype = 0L;
  510.     h.ras_maplength = 0L;
  511.     size = (long)sizeof(struct rast_head);
  512.     FSWrite(fd, &size, &h);
  513.     size = map->rowBytes * (long)map->bounds.bottom;
  514.     FSWrite(fd, &size, map->baseAddr);
  515. }
  516.  
  517. save_text(fd, map, fn)
  518. int fd;
  519. BitMap *map;
  520. char *fn;
  521. {
  522.     char outbuf[512], name[80];
  523.     long size, bytes, i;
  524.     int *bit_word, w_word;
  525.     
  526.     pStrCopy(fn, name);
  527.     PtoCstr(name);
  528.     
  529.     sprintf(outbuf, "DeclareBitmap(%s, %d, %d, %s_bits);\r",
  530.         name, map->bounds.right, map->bounds.bottom, name);
  531.     size = (long)strlen(outbuf);
  532.     FSWrite(fd, &size, outbuf);
  533.     sprintf(outbuf, "/* Format_version=1, Width=%d, Height=%d, Depth=1, Valid_bits_per_item=16\r*/\r",
  534.         map->bounds.right, map->bounds.bottom);
  535.     size = (long)strlen(outbuf);
  536.     FSWrite(fd, &size, outbuf);
  537.     sprintf(outbuf, "short %s_bits[] =\r{\r\t", name);    
  538.     size = (long)strlen(outbuf);
  539.     bytes = map->rowBytes * (long)(map->bounds.bottom) / 2L;
  540.     FSWrite(fd, &size, outbuf);
  541.     for(i = 0, w_word = 0, bit_word = (int *)map->baseAddr;
  542.             i < bytes - 1; i++) {
  543.         sprintf(outbuf, "0x%04x, ", *bit_word);
  544.         size = (long)strlen(outbuf);
  545.         FSWrite(fd, &size, outbuf);
  546.         bit_word++;
  547.         w_word = (w_word + 1) & 0x7;
  548.         if (w_word == 0) {
  549.             size = 2L;
  550.             FSWrite(fd, &size, "\r\t");
  551.         }
  552.     }
  553.     sprintf(outbuf, "0x%04x\r}\r", *bit_word);
  554.     size = (long)strlen(outbuf);
  555.     FSWrite(fd, &size, outbuf);
  556. }
  557.  
  558. GetFileName(fn, vRef)
  559. Str255    *fn;
  560. int        *vRef;
  561. {
  562.     SFTypeList    myTypes;
  563.     static Point SFGwhere = {90, 82};
  564.     
  565.     /* asks for a file name. returns true upon valid selection */
  566.     myTypes[0]='PNTG';
  567.     SFGetFile( SFGwhere, "\p", 0L, 1, myTypes, 0L, &reply );
  568.     if (reply.good) {
  569.         pStrCopy(reply.fName, fn);
  570.         *vRef = reply.vRefNum;
  571.         return(1);
  572.     }
  573.     else return(0);
  574. }
  575.  
  576. SetFileName(fn, vRef)
  577. Str255    *fn;
  578. int        *vRef;
  579. {
  580.     static Point SFPwhere = {90, 82};
  581.  
  582.     SFPutFile(SFPwhere, "\p", fn, 0L, &reply);
  583.     if (reply.good) {
  584.         pStrCopy(reply.fName, fn);
  585.         *vRef = reply.vRefNum;
  586.         return(1);
  587.     }
  588.     else return(0);
  589. }
  590.  
  591. CloseMP()
  592. {
  593.     DisposPtr(MPmap.baseAddr);        /* free docment memory */
  594.     MPmap.baseAddr = 0L;            /* nil the pointer */
  595.     mpopen = 0;                        /* clear open flag */
  596.     SetWTitle(myWindow, "\PUntitled");    /* untitle window */
  597.     FillRect(&(myWindow->portRect), white);    /* clean window */
  598. }
  599.  
  600. pStrCopy( p1, p2 )
  601. register char *p1, *p2;
  602. /* copies a pascal string from p1 to p2 */
  603. {
  604.     register int len;
  605.     
  606.     len = *p2++ = *p1++;
  607.     while (--len>=0) *p2++=*p1++;
  608. }
  609.  
  610. MyError( s, f )
  611. Str255 s, f;
  612. {
  613.     ParamText(s, f,"\p", "\p");
  614.     Alert(ErrorAlert, 0L);
  615. }
  616.  
  617. DispMP()
  618. {
  619.     Rect drect;
  620. /* displays a section of a macpaint document starting at px, py which
  621.  * are relative to the macpaint document, 0,0 being the upper left corner.
  622.  * ww and wh are the internal dimensions of the window
  623.  */
  624.     SetRect(&drect, px, py, px + ww, py + wh);
  625.     CopyBits(&(MPmap), &(myWindow->portBits), &drect,
  626.         &(myWindow->portRect), srcCopy, 0L);
  627. }
  628.  
  629. Select(where)
  630. Point where;
  631. {
  632. /* allows the selection of a section of a macpaint document.
  633.  * This lets the user sweep out a section of the document, and
  634.  * does auto scrolling if needed, so a section larger than the screen can
  635.  * be selected.  If a valid rectangle was selected, it will set the
  636.  * selcted flag and leave the selected rectangle in the global srect,
  637.  * in corrdinates in terms of the document.
  638.  */
  639.     Rect drect, rrect1, rrect2;
  640.     Point corner, cmouse;
  641.     register int dx, dy;
  642.     
  643.     GlobalToLocal(&where); /* get correct coordinate system */
  644.  
  645.     corner.h = where.h;
  646.     corner.v = where.v;
  647.     SetRect(&srect, px + corner.h, py + corner.v,
  648.          px + corner.h, py + corner.v);
  649.     /* set the document selection rectangle */
  650.     SetRect(&rrect1, corner.h, corner.v, corner.h, corner.v);
  651.     /* set the selection rectangle */
  652.     PenMode(patXor); /* use xor drawing for easy animation */
  653.     if (selected) {
  654.         /* something has already been selected, wipe it away */
  655.         SetRect(&drect, px, py, px + ww, py + wh);
  656.         CopyBits(&(MPmap), &(myWindow->portBits), &drect,
  657.             &(myWindow->portRect), srcCopy, 0L);
  658.     }
  659.     FrameRect(&rrect1);    /* draw in first rectangle */
  660.     while (StillDown()) {    /* loop until selected */
  661.         GetMouse(&cmouse);
  662.         if (cmouse.h > ww || cmouse.h< 0 || cmouse.v > wh || cmouse.v< 0) {
  663.         /* if the mouse is out of bounds, determine amount to scroll */
  664.             dx = dy = 0;
  665.             if (cmouse.h > ww) {
  666.                 if (px + ww + 16 > PAINT_WIDE) {
  667.                 /* scroll as much as possible, but make sure we only
  668.                  * display the painting, and nothing extra
  669.                  */
  670.                     dx = (PAINT_WIDE - (px + ww));
  671.                     if (dx < 0) dx = 0;
  672.                 }
  673.                 else dx = 16;
  674.             }
  675.             if (cmouse.h < 0) {
  676.                 if (px - 16 < 0) {
  677.                     dx = px;
  678.                 }
  679.                 else dx = -16;
  680.             }
  681.             if (cmouse.v > wh) {
  682.                 if (py + wh + 16 > PAINT_HIGH) {
  683.                     dy = (PAINT_HIGH - (py + wh));
  684.                     if (dy < 0) dy = 0;
  685.                 }
  686.                 else dy = 16;
  687.             }
  688.             if (cmouse.v < 0) {
  689.                 if (py - 16 < 0) {
  690.                     dy = py;
  691.                 }
  692.                 else dy = -16;
  693.             }
  694.             px += dx;    /* offset corner of display */
  695.             py += dy;
  696.             OffsetRect(&rrect1, -dx, -dy);    /* offset select rect */
  697.             corner.h -= dx;    /* change corner of selection rect */
  698.             corner.v -= dy;
  699.             if (dx < 0) rrect1.left += dx; /* rect up or down? */
  700.             else rrect1.right += dx;
  701.             if (dy < 0) rrect1.top += dy;
  702.             else rrect1.bottom += dy;
  703.             SetRect(&drect, px, py, px + ww, py + wh);
  704.             CopyBits(&(MPmap), &(myWindow->portBits), &drect,
  705.                 &(myWindow->portRect), srcCopy, 0L);
  706.             FrameRect(&rrect1);
  707.         }
  708.         else {
  709.         /* get new select rectangle */
  710.             SetRect(&rrect2, corner.h, corner.v, cmouse.h, cmouse.v);
  711.         /* sort it so that left is really left and top is really top */
  712.             SortRect(&rrect2);
  713.             if(rrect1.bottom != rrect2.bottom || 
  714.                 rrect1.left != rrect2.left ||
  715.                 rrect1.right != rrect2.right ||
  716.                 rrect1.top != rrect2.top) {
  717.                 /* if the rects differ, draw the new, and erase the old */
  718.                 FrameRect(&rrect2);
  719.                 FrameRect(&rrect1);
  720.                 rrect1 = rrect2;
  721.             }
  722.         }
  723.     } /* end while(StillDown()); */
  724.  
  725.     if (cmouse.h < 0) cmouse.h = 0;
  726.     if (cmouse.h > ww) cmouse.h = ww;
  727.     if (cmouse.v < 0) cmouse.v = 0;
  728.     if (cmouse.v > wh) cmouse.v = wh;
  729.     
  730.     srect.right = px + cmouse.h;
  731.     srect.bottom = py + cmouse.v;
  732.     SortRect(&srect); /* sort the selection rect */
  733.     if (srect.top != srect.bottom && srect.left != srect.right) {
  734.         /* a valid selection was made */
  735.         selected = 1;
  736.     }
  737.     else {
  738.         /* redraw the screen */
  739.         SetRect(&drect, px, py, px + ww, py + wh);
  740.         CopyBits(&(MPmap), &(myWindow->portBits), &drect,
  741.             &(myWindow->portRect), srcCopy, 0L);
  742.     }
  743. }
  744.  
  745. SortRect(r)
  746. register Rect *r;
  747. {
  748. /* sorts the rectangle so left is truly left of right, and
  749.  * top is truly above the bottom.   The Macintosh rect routines
  750.  * puke if they don't get the "correct" coords.
  751.  */
  752.     register int bucket;
  753.     
  754.     if (r->left > r->right) {
  755.         bucket = r->left;
  756.         r->left = r->right;
  757.         r->right = bucket;
  758.     }
  759.     if (r->top > r->bottom) {
  760.         bucket = r->top;
  761.         r->top = r->bottom;
  762.         r->bottom = bucket;
  763.     }
  764. }
  765.  
  766. TrackHand(where)
  767. Point where;
  768. {
  769. /* this tracks the hand cursor to allow the user to scroll around the
  770.  * document fairly swiftly.
  771.  */
  772.     Rect drect;
  773.     Point cmouse;
  774.     register int x, y, xlim, ylim;
  775.     
  776.     xlim = PAINT_WIDE - ww;    /* screen limits */
  777.     ylim = PAINT_HIGH - wh;
  778.     x = px;
  779.     y = py;
  780.     GlobalToLocal(&where);
  781.     selected = 0;    /* unselect rectangle */
  782.     HideCursor();    /* get rid of the hand for a better appearance */
  783.     while(StillDown()) {
  784.         GetMouse(&cmouse);    /* current mouse */
  785.         x += (where.h - cmouse.h);    /* scroll the difference in coords */
  786.         y += (where.v - cmouse.v);
  787.         where = cmouse;
  788.         /* make it in bounds */
  789.         if (x < 0) x = 0;
  790.         if (x > xlim) x = xlim;
  791.         if (y < 0) y = 0;
  792.         if (y > ylim) y = ylim;
  793.         SetRect(&drect, x, y, x + ww, y + wh); /* new subrect to display */
  794.         CopyBits(&(MPmap), &(myWindow->portBits), &drect,
  795.             &(myWindow->portRect), srcCopy, 0L);
  796.     }
  797.     px = x;            /* final upper left corner */
  798.     py = y;
  799.     DispMP();        /* draw it for good measure */
  800.     ShowCursor();    /* return the cursor */
  801. }
  802.  
  803. Pick_Format()
  804. {
  805.     DialogPtr myDialog;
  806.     GrafPort *saveport;
  807.     int itemhit, itemtype, fmt;
  808.     Handle theitem;
  809.     Rect r;
  810.     
  811.     GetPort(&saveport);
  812.     myDialog = GetNewDialog(Formats, 0L, -1L);
  813.     SetPort(myDialog);
  814.     ShowWindow(myDialog);
  815.     GetDItem(myDialog, format, &itemtype, &theitem, &r);
  816.     SetCtlValue((ControlHandle)theitem, 1);
  817.     DrawDialog(myDialog);
  818.     fmt = format;
  819.     GetDItem(myDialog, fmt, &itemtype, &theitem, &r);
  820.     SetCtlValue((ControlHandle)theitem, 1);
  821.     do {
  822.         ModalDialog(0L, &itemhit);
  823.         if (itemhit != fmt && (itemhit >= MGR_FMT && itemhit <= TEXT_FMT)){
  824.             GetDItem(myDialog, itemhit, &itemtype, &theitem, &r);
  825.             SetCtlValue((ControlHandle)theitem, 1);
  826.             GetDItem(myDialog, fmt, &itemtype, &theitem, &r);
  827.             SetCtlValue((ControlHandle)theitem, 0);
  828.             fmt = itemhit;
  829.         }
  830.     } while (itemhit != 1);
  831.     DisposDialog(myDialog);
  832.     SetPort(saveport);
  833.     return(fmt);
  834. }
  835.  
  836. strlen(s)
  837. register char *s;
  838. {
  839. char *s0 = s;
  840.  
  841.     while (*s++);
  842.     return (s-s0-1);
  843. }
  844.